﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Framework.Bus;
using Framework.Infrastructure;
using Framework.Event;
using Microsoft.Practices.Unity;
using System.IO;
using System.Xml.Linq;
using Framework.Command;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using Framework.Domain;

namespace Framework.Config
{
    public class Configuration
    {
        static Configuration _Instance = new Configuration();
        public static Configuration Instance { get { return _Instance; } }

        public UnityConfigurationSection UnityConfigurationSection
        {
            get
            {
                return (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            }
        }

        Configuration()
        {

        }

        public static T GetAppConfig<T>(string key)
        {
            T val = default(T);
            try
            {
                var value = GetAppConfig(key);
                if (typeof(T).IsEquivalentTo(typeof(Guid)))
                {
                    val = (T)Convert.ChangeType(new Guid(value), typeof(T));
                }
                else
                {
                    val = (T)Convert.ChangeType(value, typeof(T));
                }

            }
            catch (Exception)
            {

            }
            return val;
        }
        public static string GetAppConfig(string keyname, string configPath = "Config")
        {
            var config = System.Configuration.ConfigurationManager.AppSettings[keyname];
            try
            {
                if (string.IsNullOrWhiteSpace(config))
                {
                    string filePath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, configPath);
                    using (TextReader reader = new StreamReader(filePath))
                    {
                        XElement xml = XElement.Load(filePath);
                        if (xml != null)
                        {
                            var element = xml.Elements().SingleOrDefault(e => e.Attribute("key") != null && e.Attribute("key").Value.Equals(keyname));
                            if (element != null)
                            {
                                config = element.Attribute("value").Value;
                            }
                        }
                    }
                }
            }
            catch (System.Exception)
            {
                config = string.Empty;
            }
            return config;
        }


        public Configuration OnlySyncEventBusBuild()
        {
            AggregateRootEventHandlerBuild();
            SyncEventDispatcherBuild();
            SyncEventBusBuild();
            return this;
        }

        public Configuration DefaultEventBusBuild()
        {
            AggregateRootEventHandlerBuild();
            SyncEventDispatcherBuild();
            SyncEventBusBuild();
            AsyncEventBusBuild();
            return this;
        }
        public Configuration AggregateRootEventHandlerBuild()
        {
            MessageDispatcherUtility.RegisterHandlers(AggregateRoot.EventDispatcher, HandlerKind.AggregateRoot, false);
            return this;
        }

        public Configuration SyncEventDispatcherBuild(IMessageDispatcher dispatcher = null)
        {
            if (dispatcher == null)
            {
                dispatcher = IoCFactory.Resolve<IMessageDispatcher>(Constants.Configuration.SyncEventDispatcher);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                         .RegisterInstance(typeof(IMessageDispatcher),
                                           Constants.Configuration.SyncEventDispatcher
                                           , dispatcher
                                           , new ContainerControlledLifetimeManager());
            }
            MessageDispatcherUtility.RegisterHandlers(dispatcher, HandlerKind.Event, false);
            return this;
        }

        public Configuration AsyncEventDispatcherBuild(IMessageDispatcher dispatcher = null)
        {
            if (dispatcher == null)
            {
                dispatcher = IoCFactory.Resolve<IMessageDispatcher>(Constants.Configuration.AsyncEventDispatcher);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                         .RegisterInstance(typeof(IMessageDispatcher),
                                           Constants.Configuration.AsyncEventDispatcher
                                           , dispatcher
                                           , new ContainerControlledLifetimeManager());
            }
            MessageDispatcherUtility.RegisterHandlers(dispatcher, HandlerKind.Event, true);
            return this;
        }

        public Configuration SyncEventBusBuild(ISyncBus<IDomainEvent> bus = null)
        {
            if (bus == null)
            {
                IoCFactory.Resolve<ISyncBus<IDomainEvent>>(Constants.Configuration.SyncDomainEventBus);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                          .RegisterInstance(typeof(ISyncBus<IDomainEvent>),
                                            Constants.Configuration.SyncDomainEventBus
                                            , bus
                                            , new ContainerControlledLifetimeManager());
            }
            return this;
        }

        public Configuration AsyncEventBusBuild(IAsyncBus<IDomainEvent> bus = null)
        {
            if (bus == null)
            {
                IoCFactory.Resolve<IAsyncBus<IDomainEvent>>(Constants.Configuration.AsyncDomainEventBus);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                          .RegisterInstance(typeof(IAsyncBus<IDomainEvent>),
                                            Constants.Configuration.AsyncDomainEventBus
                                            , bus
                                            , new ContainerControlledLifetimeManager());
            }
            return this;
        }



        public Configuration CommandDispatcherBuild(IMessageDispatcher dispatcher = null)
        {
            if (dispatcher == null)
            {
                dispatcher = IoCFactory.Resolve<IMessageDispatcher>(Constants.Configuration.CommandDispatcher);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                         .RegisterInstance(typeof(IMessageDispatcher),
                                           Constants.Configuration.CommandDispatcher
                                           , dispatcher
                                           , new ContainerControlledLifetimeManager());
            }
            MessageDispatcherUtility.RegisterHandlers(dispatcher, HandlerKind.Command, false);
            return this;
        }

        public Configuration SyncCommandBusBuild(ISyncBus<ICommand> bus = null)
        {
            if (bus == null)
            {
                IoCFactory.Resolve<ISyncBus<ICommand>>(Constants.Configuration.SyncCommandBus);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                         .RegisterInstance(typeof(ISyncBus<ICommand>),
                                           Constants.Configuration.SyncCommandBus
                                           , bus
                                           , new ContainerControlledLifetimeManager());
            }
            return this;
        }


        public Configuration AsyncCommandBusBuild(IAsyncBus<ICommand> bus = null)
        {
            if (bus == null)
            {
                IoCFactory.Resolve<IAsyncBus<ICommand>>(Constants.Configuration.AsyncCommandBus);
            }
            else
            {
                IoCFactory.Instance.CurrentContainer
                         .RegisterInstance(typeof(IAsyncBus<ICommand>),
                                           Constants.Configuration.AsyncCommandBus
                                           , bus
                                           , new ContainerControlledLifetimeManager());
            }
            return this;
        }


        public Configuration OnlySyncCommandBusBuild()
        {
            CommandDispatcherBuild();
            SyncCommandBusBuild();
            return this;
        }

        public Configuration DefaultCommandBusBuild()
        {
            CommandDispatcherBuild();
            SyncCommandBusBuild();
            AsyncCommandBusBuild();
            return this;
        }


    }
}
